/*!
 * iny-bus.js v1.1.0
 * (c) 2019-2020 landluck
 * Released under the MIT License.
 */
'use strict';

/**
 * 创建唯一id
 */
function createUid() {
  return Math.random().toString().substr(2);
}
function once(fn) {
  var called = false;
  return function () {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
      args[_i] = arguments[_i];
    }
    if (!called) {
      called = true;
      fn.apply(this, args);
    }
  };
}

var EventBus = /** @class */ (function () {
  function EventBus() {
    /**
     * 储存事件的容器
     */
    this.events = [];
  }
  /**
   * on 新增事件监听
   * @param name 事件名
   * @param execute 回调函数
   * @param ctx 上下文 this
   * @returns { string } eventId 事件ID，用户取消该事件监听
   */
  EventBus.prototype.on = function (name, execute, ctx) {
    return this.addEvent(name, execute, ctx);
  };
  /**
   * one 只允许添加一次事件监听
   * @param name 事件名
   * @param execute 回调函数
   * @param ctx 上下文 this
   * @returns { string } eventId 事件ID，用户取消该事件监听
   */
  EventBus.prototype.once = function (name, execute, ctx) {
    return this.addEvent(name, once(execute), ctx);
  };
  /**
   * remove 移除事件监听
   * @param name 事件名
   * @param eventId 移除单个事件监听需传入
   * @returns { EventBus } EventBus EventBus 实例
   */
  EventBus.prototype.remove = function (name, eventId) {
    var events = this.events;
    var index = events.findIndex(function (event) {
      return event.name === name;
    });
    if (index === -1) {
      return this;
    }
    if (!eventId) {
      events.splice(index, 1);
      return this;
    }
    var executeIndex = events[index].executes.findIndex(function (item) {
      return item.id === eventId;
    });
    if (executeIndex !== -1) {
      events[index].executes.splice(executeIndex, 1);
    }
    return this;
  };
  /**
   * emit 派发事件
   * @param name 事件名
   * @param args 其余参数
   * @returns { EventBus } EventBus EventBus 实例
   */
  EventBus.prototype.emit = function (name) {
    var args = [];
    for (var _i = 1; _i < arguments.length; _i++) {
      args[_i - 1] = arguments[_i];
    }
    var event = this.find(name);
    if (!event) {
      return this;
    }
    var funcs = event.executes;
    funcs.forEach(function (func) {
      if (func.ctx) {
        return func.execute.apply(func.ctx, args);
      }
      func.execute.apply(func, args);
    });
    return this;
  };
  /**
   * 查找事件的方法
   * @param name
   */
  EventBus.prototype.find = function (name) {
    var events = this.events;
    for (var i = 0; i < events.length; i++) {
      if (name === events[i].name) {
        return events[i];
      }
    }
    return null;
  };
  EventBus.prototype.clear = function () {
    this.events.length = 0;
    return this;
  };
  /**
   * 添加事件的方法
   * @param name
   * @param execute
   */
  EventBus.prototype.addEvent = function (name, execute, ctx) {
    var eventId = createUid();
    var events = this.events;
    var event = this.find(name);
    if (event !== null) {
      event.executes.push({ id: eventId, execute: execute, ctx: ctx });
      return eventId;
    }
    events.push({
      name: name,
      executes: [
        {
          id: eventId,
          execute: execute,
          ctx: ctx,
        },
      ],
    });
    return eventId;
  };
  return EventBus;
})();

function createInstance() {
  var bus = new EventBus();
  // @ts-ignore
  return bus;
}
var bus = createInstance();
bus.create = function create() {
  return createInstance();
};

function isAliPay() {
  // @ts-ignore
  return typeof my !== 'undefined' && my.getSystemInfo;
}

var PAGE_LIFE_TIMES = {
  onLoad: 'onLoad',
  onUnload: 'onUnload',
};
var APP_LIFE_TIMES = {
  onLoad: 'onLaunch',
  onUnload: '',
};
var COMPONENT_LIFE_TIMES = isAliPay()
  ? {
      onLoad: 'onInit',
      onUnload: 'didUnmount',
    }
  : {
      onLoad: 'created',
      onUnload: 'detached',
    };

function verifyEvents(busEvents) {
  if (!busEvents || typeof busEvents !== 'object') {
    return false;
  }
  return true;
}
function onLoad(ctx, onLoad) {
  var func = ctx[onLoad];
  ctx[onLoad] = function (options) {
    var ids = addEvent(ctx.busEvents, this);
    ctx.__inyEventIds = ids;
    func && func.call(this, options);
  };
}
function onUnload(ctx, onUnload) {
  if (!onUnload) {
    return;
  }
  var func = ctx[onUnload];
  ctx[onUnload] = function () {
    ctx.__inyEventIds.forEach(function (event) {
      return bus.remove(event.name, event.id);
    });
    ctx.__inyEventIds = undefined;
    func && func.call(this);
  };
}
function addEvent(events, ctx) {
  return Object.keys(events)
    .map(function (name) {
      var event = events[name];
      if (typeof event === 'function') {
        return { id: bus.on(name, event.bind(ctx)), name: name };
      }
      if (typeof event.handler !== 'function') {
        return { id: '', name: name };
      }
      if (event.once) {
        return { id: bus.once(name, event.handler.bind(ctx)), name: name };
      }
      return { id: bus.on(name, event.handler.bind(ctx)), name: name };
    })
    .filter(function (item) {
      return !!item.id;
    });
}

function inyApp(ctx) {
  var busEvents = ctx.busEvents;
  if (!verifyEvents(busEvents)) {
    return ctx;
  }
  onLoad(ctx, APP_LIFE_TIMES.onLoad);
  onUnload(ctx, APP_LIFE_TIMES.onUnload);
  return ctx;
}

function InyPage(ctx) {
  var busEvents = ctx.busEvents;
  if (!verifyEvents(busEvents)) {
    return ctx;
  }
  onLoad(ctx, PAGE_LIFE_TIMES.onLoad);
  onUnload(ctx, PAGE_LIFE_TIMES.onUnload);
  return ctx;
}

function InyComponents(ctx) {
  var busEvents = ctx.busEvents;
  if (!verifyEvents(busEvents)) {
    return ctx;
  }
  onLoad(ctx, COMPONENT_LIFE_TIMES.onLoad);
  onUnload(ctx, COMPONENT_LIFE_TIMES.onUnload);
  return ctx;
}

bus.app = inyApp;
bus.page = InyPage;
bus.component = InyComponents;

module.exports = bus;
